<template>
  <view class="tv-scroll-view">
    <scroll-view :class="`scroll_${_uid}`" :style="{ width, height }" :scroll-x="scrollX" :scroll-y="scrollY" :scroll-top="scrollTop" :scroll-left="scrollLeft" :lower-threshold="lowerThreshold" @scroll="scroll" @scrolltolower="scrolltolower">
      <view class="tv-scroll-view__content">
        <slot></slot>
      </view>
    </scroll-view>
  </view>
</template>

<script>
/**
 * tv-scroll-view 可滚动视图区域
 * @description 类似于scroll-view，用于区域滚动，需要在tv-page内使用
 * @property { width } 宽度, scroll-x为true时必须设置
 * @property { height } 高度, scroll-y为true时必须设置
 * @property { scrollX } 允许横向滚动
 * @property { scrollY } 允许纵向滚动
 * @property { lowerThreshold } 距底部/右边多远时（单位px），触发 scrolltolower 事件，默认值50
 * @event { scroll } 滚动时触发
 * @event { scrolltolower } 滚动到底部/右边，会触发 scrolltolower 事件
 */
import mixin from '../../mixin/mixin.js';

export default {
  name: 'TvScrollView',
  componentName: 'TvScrollView',
  mixins: [mixin],
  props: {
    // 宽度
    width: {
      type: String,
      default: 'auto'
    },
    // 高度
    height: {
      type: String,
      default: 'auto'
    },
    // 允许横向滚动
    scrollX: {
      type: Boolean,
      default: false
    },
    // 允许纵向滚动
    scrollY: {
      type: Boolean,
      default: false
    },
    // 距底部/右边多远时（单位px），触发 scrolltolower 事件
    lowerThreshold: {
      type: Number,
      default: 50
    }
  },
  inject: ['tvPage', 'tvArea'],
  data: () => ({
    scrollTop: 0, // 竖向滚动条位置
    scrollLeft: 0, // 横向滚动条位置
    rect: {} // 节点信息
  }),
  watch: {
    'tvArea.focused': {
      immediate: true,
      handler(val) {
        this.tvArea.hasFocus && val && this.viewKeyMove(val);
      }
    }
  },
  methods: {
    /**
    * 焦点移动，使当前焦点元素尽可能在中心位置
    * @param {Object} view 当前焦点元素
    */
    viewKeyMove(view) {
      const viewInfo = view.rect;
      const scrollInfo = this.rect;
      if (this.scrollX) {
        if (['left', 'right'].includes(this.tvPage.keyType)) {
          if (viewInfo.right > scrollInfo.right || this.scrollLeft > viewInfo.left) {
            this.scrollLeft = viewInfo.left - (scrollInfo.width / 2) + (viewInfo.width / 2);
          }
        }
      }
      if (this.scrollY) {
        if (['up', 'down'].includes(this.tvPage.keyType)) {
          if (viewInfo.bottom > scrollInfo.bottom || this.scrollTop > viewInfo.top) {
            this.scrollTop = viewInfo.top - (scrollInfo.height / 2) + (viewInfo.height / 2);
          }
        }
      }
    },
    // 滚动
    scroll(e) {
      this.$emit('scroll', e);
    },
    // 滚动到底部/右边
    scrolltolower(e) {
      this.$emit('scrolltolower', e);
    }
  },
  async mounted() {
    const rect = await this.$getRect(`.scroll_${this._uid}`);
    this.rect = Object.assign({}, rect, { uid: this._uid });
  }
};
</script>

<style lang="scss" scoped>
.tv-scroll-view {
  &__content {
    position: relative;
    width: 100%;
    height: 100%;
  }
}
</style>
